{-# LANGUAGE EmptyDataDecls             #-}
{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Orche.Language.Zak
-- Copyright   :  (c) Stephen Tetley 2012
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  unstable
-- Portability :  GHC
--
-- Zak patch system.
-- 
--------------------------------------------------------------------------------

module Ochre.Language.Zak
  (


    ZakIx
  , zakIx
 
  , zakinit
  , ziw
  , zkw
  , zaw

  , ziwm
  , ziwm_
  , zkwm
  , zkwm_
  , zawm
  , zawm_

  , zir
  , zkr
  , zar
  , zarg
  , zkmod
  , zamod
  , zkcl
  , zacl

  ) where

import Ochre.Compiler.VarId
import Ochre.Language.Prim



data TokZakIx

type ZakIx = PValue TokZakIx


-- | Constructor for Zak index.
--
zakIx :: IInt -> ZakIx
zakIx ma = PValue $ getPValue ma



-- | Initialize. 
--
-- Note - this is a orchestra level (not instrument level) opcode 
-- so potentially it will be removed.
-- 
-- > zakinit : isizea * isizek -> ()
--
zakinit :: IInt -> IInt -> Orch ()
zakinit isizea isizek = 
    globalInvoke (PrimId "zakinit") [getPValue isizea, getPValue isizek]



-- | Writes zak variable at i-rate without mixing.
--
-- > ziw : isig * indx -> ()
--
ziw :: IFloat -> ZakIx -> Code ()
ziw isig indx = 
    opcode0 "ziw" [ getPValue isig, getPValue indx ]


-- Note - somewhat /contradictory/ type.
--
-- > zkw : ksig *  kndx -> ()
--
-- @kndx@ is a K Rate integer, this implies we have more K Rate 
-- /types/ than just a KSignal. Maybe types should be a product
-- of Type (in the ususal Haskell sense) and Rate.
-- 
-- Idiomatically, @kndx@ is usually assigned to a pfield 
-- (out chan) and is constant for the length of the note.
--


-- | Writes zak variable at k-rate without mixing.
--
-- > zkw : ksig * kndx -> ()
--
zkw :: KSig -> ZakIx -> Code ()
zkw ksig kndx = 
    opcode0 "ziw" [ getPValue ksig, getPValue kndx ]



-- | Writes zak variable at a-rate without mixing.
--
-- > zkw : asig * kndx -> ()
--
zaw :: ASig -> ZakIx -> Code ()
zaw asig kndx = 
    opcode0 "zaw" [ getPValue asig, getPValue kndx ]


-- | Writes zak variable at i-rate with mixing.
--
-- > ziw : isig * indx -> ()
--
ziwm :: IFloat -> ZakIx -> Code ()
ziwm isig indx = 
    opcode0 "zwim" [ getPValue isig, getPValue indx ]


-- | Writes zak variable at i-rate with mixing.
--
-- > ziw : isig * indx * imix -> ()
--
-- (Needs checking that Bool istranslated to 0 or 1).
--
ziwm_ :: IFloat -> ZakIx -> IBool -> Code ()
ziwm_ isig indx imix = 
    opcode0 "zwim" [ getPValue isig, getPValue indx
                   , getPValue imix ]




-- | Writes zak variable at k-rate with mixing.
--
-- > ziw : ksig * kndx -> ()
--
zkwm :: KSig -> ZakIx -> Code ()
zkwm ksig kndx = 
    opcode0 "zwkm" [ getPValue ksig, getPValue kndx ]


-- | Writes zak variable at k-rate with mixing.
--
-- > ziw : ksig * kndx * imix -> ()
--
zkwm_ :: KSig -> ZakIx -> IBool -> Code ()
zkwm_ ksig kndx kmix = 
    opcode0 "zwkm" [ getPValue ksig, getPValue kndx 
                   , getPValue kmix ]



-- | Writes zak variable at a-rate with mixing.
--
-- > zawm : asig * kndx -> ()
--
zawm :: KSig -> ZakIx -> Code ()
zawm asig kndx = 
    opcode0 "zawm" [ getPValue asig, getPValue kndx ]


-- | Writes zak variable at a-rate with mixing.
--
-- > ziw : asig * kndx * kmix -> ()
--
zawm_ :: KSig -> ZakIx -> IBool -> Code ()
zawm_ asig kndx kmix = 
    opcode0 "zawm" [ getPValue asig, getPValue kndx
                   , getPValue kmix ]



-- | Read a zak variable at i-rate.
--
-- > zir : indx -> ir
--
zir :: ZakIx -> GenISig
zir indx = 
    opcode1 "zir" [ getPValue indx ]


-- | Read a zak variable at k-rate.
--
-- > zkr : kndx -> kres
--
zkr :: ZakIx -> GenKSig
zkr kndx = 
    opcode1 "zkr" [ getPValue kndx ]


-- | Read a zak variable at a-rate.
--
-- > zar : kndx -> ares
--
zar :: ZakIx -> GenASig
zar kndx = 
    opcode1 "zar" [ getPValue kndx ]


-- | Read a zak variable at a-rate add some gain.
--
-- > zarg : kndx * kgain -> ares
--
zarg :: ZakIx -> KSig -> GenASig
zarg kndx kgain = 
    opcode1 "zarg" [ getPValue kndx, getPValue kgain ]


-- | Modulate one k-rate signal by another.
--
-- > zkmod : ksig * kzkmod -> kres
--
zkmod :: KSig -> ZakIx -> GenKSig
zkmod ksig kzkmod = 
    opcode1 "zkmod" [ getPValue ksig, getPValue kzkmod ]


-- | Modulate one a-rate signal by another.
--
-- > zamod : asig * kzamod -> ares
--
-- Note - zakIx can be negated to mean multiplicative modulation.
-- This is /obscure/ - potentially we need a more Haskell-like 
-- API.
--
zamod :: ASig -> ZakIx -> GenASig
zamod asig kzamod = 
    opcode1 "zamod" [ getPValue asig, getPValue kzamod ]


-- | Clear range of zak variables - k-rate.
--
-- > zkcl : kfirst * klast -> ()
--
zkcl  :: ZakIx -> ZakIx -> Code ()
zkcl kfirst klast = 
    opcode0 "zkcl" [ getPValue kfirst, getPValue klast ]


-- | Clear range of zak variables - k-rate.
--
-- > zacl : kfirst * klast -> ()
-- 
zacl  :: ZakIx -> ZakIx -> Code ()
zacl kfirst klast = 
    opcode0 "zacl" [ getPValue kfirst, getPValue klast ]

